#include "Epoller.h"
#include "Channel.h"
#include "EventLoop.h"

#include "Logger.h"

Epoller::Epoller(EventLoop* loop) : loop_(loop), evs_(EPOLL_WAIT_NUM) {
    epfd_ = epoll_create(EPOLL_CREATE_SIZE);
    LOG_INFO("epoll_create success, epfd = %d", epfd_);
    if (epfd_ < 0) {
        LOG_INFO("epoll create fail.");
        abort();
    }
}

int Epoller::EpollCtl(Channel* channel, int op) {
    int fd = channel->Fd();
    struct epoll_event ee;
    memset(&ee, 0, sizeof(ee));
    ee.events = channel->Events();
    ee.data.ptr = channel;
    ee.data.fd = fd;
    int ret = epoll_ctl(epfd_, op, fd, &ee);
    return ret;
}

void Epoller::UpdateChannel(Channel* channel) {
    int fd = channel->Fd();
    auto it = channel_map_.find(fd);
    if (it == channel_map_.end()) {
        EpollCtl(channel, EPOLL_CTL_ADD);
        channel_map_.insert(std::make_pair(fd, channel));
    } else {
        EpollCtl(channel, EPOLL_CTL_MOD);
    }
}

void Epoller::RemoveChannel(Channel* channel) {
    int fd = channel->Fd();
    auto it = channel_map_.find(fd);
    if (it == channel_map_.end())
        return;
    if (EpollCtl(channel, EPOLL_CTL_DEL) < 0)
        LOG_ERROR("remove channel fail!");
    else {
        channel_map_.erase(fd);
        LOG_INFO("remove fd = %d", fd);
    }
}

void Epoller::EpollWait(std::vector<Channel*>* active_channels, int flag) {
    int ret = epoll_wait(epfd_, evs_.data(), evs_.size(), 1000);
    if (ret < 0) {
        LOG_INFO("epoll_wait fail.");
        return;
    }
    int size = evs_.size();
    if (ret == size) {
        evs_.resize(2 * size);
    }
    for (int i = 0; i < ret; i++) {
        int fd = evs_[i].data.fd;
        Channel* channel = static_cast<Channel*>(channel_map_[fd]);
        if (channel) {
            channel->SetRevents(evs_[i].events);
            active_channels->push_back(channel);
            // EventLoop拿到了它的Poller给返回的所有发生事件的channel列表
        }
    }
}

Epoller::~Epoller() {
    if (epfd_) {
        close(epfd_);
    }
}
